#include "stdafx.h"

Texture::Texture(String^ argName, int argWidth, int argHeight, int argFrameWidth, int argFrameHeight) : mName(argName), mWidth(argWidth), mHeight(argHeight), mFrameWidth(argFrameWidth), mFrameHeight(argFrameHeight)
{
    // Make sure the texture parameters are valid
    if (mWidth % mFrameWidth)
        throw gcnew Exception("The texture width must be evenly divisible by the frame width");

    if (mHeight % mFrameHeight)
        throw gcnew Exception("The texture height must be evenly divisible by the frame height");

    mFramesPerRow = mWidth / mFrameWidth;
    mFloatFrameWidth = mFrameWidth / (float)mWidth;
    mFloatFrameHeight = mFrameHeight / (float)mHeight;
}

Texture::Texture(void)
{
}


Texture::~Texture(void)
{
    if (mReferenceCount)
    {
        smLogger->Warn("{0} outstanding references to texture pointer '{1}'", mReferenceCount, mName);
        SAFE_RELEASE_INTPTR(mTexturePointer);
    }
}


String^ Texture::Name::get(void)
{
    return mName;
}


int Texture::Height::get(void)
{
    return mHeight;
}


int Texture::Width::get(void)
{
    return mWidth;
}


IntPtr Texture::NativeTexturePointer::get(void)
{
    return mTexturePointer;
}


int Texture::FrameHeight::get(void)
{
    return mFrameHeight;
}


int Texture::FrameWidth::get(void)
{
    return mFrameWidth;
}


void Texture::AddReference(void)
{
    if (!(mReferenceCount++))
    {
        mTexturePointer = Engine::GetRenderer()->CreateTexture(String::Format("data/texture/{0}.png", mName));
    }
}


void Texture::Release(void)
{
    if (!(--mReferenceCount))
    {
        SAFE_RELEASE_INTPTR(mTexturePointer);
    }
}


Frame Texture::GetFrame(int argFrameId)
{
    if (argFrameId < 0)
        throw gcnew ArgumentException("Frame Id must be greater than or equal to zero", "argFrameId");

    return Frame(
        argFrameId,
        mFloatFrameWidth * (argFrameId % mFramesPerRow),
        mFloatFrameHeight * (argFrameId / mFramesPerRow),
        mFloatFrameWidth,
        mFloatFrameHeight);
}


void Texture::ReadXml(XmlReader^ reader) 
{
    XmlDocument doc;

    // Load the XML document and get the document element
    doc.Load(reader);
    XmlElement^ textureElement = doc.DocumentElement;

    // Make sure the texture element has no children
    if (textureElement->HasChildNodes)
    {
        throw gcnew XmlException("Texture element may not have child nodes.");
    }

    // Get texture attributes
    mName = textureElement->GetAttribute("name");
    mWidth = Int32::Parse(textureElement->GetAttribute("width"));
    mHeight = Int32::Parse(textureElement->GetAttribute("height"));
    mFrameWidth = Int32::Parse(textureElement->GetAttribute("frameWidth"));
    mFrameHeight = Int32::Parse(textureElement->GetAttribute("frameHeight"));

    // Make sure the texture parameters are valid
    if (mWidth % mFrameWidth)
        throw gcnew Exception("The texture width must be evenly divisible by the frame width");

    if (mHeight % mFrameHeight)
        throw gcnew Exception("The texture height must be evenly divisible by the frame height");

    mFramesPerRow = mWidth / mFrameWidth;
    mFloatFrameWidth = mFrameWidth / (float)mWidth;
    mFloatFrameHeight = mFrameHeight / (float)mHeight;
}


void Texture::WriteXml(XmlWriter^ writer)
{
    throw gcnew System::NotImplementedException();
}


XmlSchema^ Texture::GetSchema(void)
{
    return nullptr;
}


/*
Texture^ Texture::Load(String^ argFile) 
{
    smLogger->Info("Creating Texture: " + argFile + ".");

    try
    {
        // Deserialize the texture from xml
        XmlSerializer serializer(Texture::typeid);
        return (Texture^)serializer.Deserialize(gcnew FileStream(argFile, System::IO::FileMode::Open, System::IO::FileAccess::Read));
    }
    catch (XmlException^ ex)
    {
        smLogger->ErrorException(L"Error reading Texture XML.", ex);
    }
}
*/